﻿using FirstFloor.ModernUI.Presentation;
using FirstFloor.ModernUI.Windows.Controls;
using FirstFloor.ModernUI.Windows.Navigation;
using LinnerToolkit.Desktop.ModernUI.Mvvm;
using LinnerToolkit.Desktop.ModernUI.Navigation;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using SimulationPTSystem.DAL;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using System.Windows.Input;

namespace SimulationPTSystem.ViewModels
{
    public class UserInfoPageViewModel : ModernViewModelBase
    {
        private string chengYuanCode;
        private string chengYuanName;
        private string ageStart;
        private string ageEnd;
        private string chengYuanGender;
        private ObservableCollection<ChengYuanInfo> chengYuanInfos;
        private ChengYuanInfo selectedChengYuanInfo;
        private EditChengYuanInfo editChengYuanInfo;

        /// <summary>
        /// 查询人员编号
        /// </summary>
        public string ChengYuanCode { get => chengYuanCode; set => Set(ref chengYuanCode, value); }
        /// <summary>
        /// 查询人员姓名
        /// </summary>
        public string ChengYuanName { get => chengYuanName; set => Set(ref chengYuanName, value); }
        /// <summary>
        /// 查询人员年龄起始
        /// </summary>
        public string AgeStart { get => ageStart; set => Set(ref ageStart, value); }
        /// <summary>
        /// 查询人员年龄结束
        /// </summary>
        public string AgeEnd { get => ageEnd; set => Set(ref ageEnd, value); }
        /// <summary>
        /// 查询人员性别
        /// </summary>
        public string ChengYuanGender { get => chengYuanGender; set => Set(ref chengYuanGender, value); }
        /// <summary>
        /// 查询到的人员列表
        /// </summary>
        public ObservableCollection<ChengYuanInfo> ChengYuanInfos { get => chengYuanInfos; set => Set(ref chengYuanInfos, value); }
        /// <summary>
        /// 选中的人员
        /// </summary>
        public ChengYuanInfo SelectedChengYuanInfo { get => selectedChengYuanInfo; set => Set(ref selectedChengYuanInfo, value); }
        /// <summary>
        /// 正在编辑的人员
        /// </summary>
        public EditChengYuanInfo EditChengYuanInfo { get => editChengYuanInfo; set => Set(ref editChengYuanInfo, value); }

        /// <summary>
        /// 性别列表
        /// </summary>
        public List<string> Genders { get; }

        /// <summary>
        /// 查询命令
        /// </summary>
        public ICommand QueryCommand { get; }
        /// <summary>
        /// 清除命令
        /// </summary>
        public ICommand ClearCommand { get; }
        /// <summary>
        /// 查看详细信息命令
        /// </summary>
        public ICommand DetailsCommand { get; }
        /// <summary>
        /// 添加人员命令
        /// </summary>
        public ICommand AddCommand { get; }
        /// <summary>
        /// 删除人员命令
        /// </summary>
        public ICommand DeleteCommand { get; }
        /// <summary>
        /// 保存命令
        /// </summary>
        public ICommand SaveCommand { get; }
        /// <summary>
        /// 取消命令
        /// </summary>
        public ICommand CancelCommand { get; }

        /// <summary>
        /// 导入成员指令
        /// </summary>
        public ICommand ImportCommand { get; }

        public UserInfoPageViewModel(IModernNavigationService navigationService) : base(navigationService)
        {
            Genders = new List<string> { "男", "女" };

            QueryCommand = new RelayCommand((obj) =>
              {
                  int ageFrom = -1;
                  int ageTo = -1;

                  if (!string.IsNullOrEmpty(AgeStart))
                  {
                      if (!int.TryParse(AgeStart.Trim(), out ageFrom) || ageFrom < 0)
                      {
                          ModernDialog.ShowMessage("请输入正确的年龄", string.Empty, System.Windows.MessageBoxButton.OK);
                          return;
                      }
                  }

                  if (!string.IsNullOrEmpty(AgeEnd))
                  {
                      if (!int.TryParse(AgeEnd.Trim(), out ageTo) || ageTo < ageFrom)
                      {
                          ModernDialog.ShowMessage("请输入正确的年龄", string.Empty, System.Windows.MessageBoxButton.OK);
                          return;
                      }
                  }

                  ChengYuanInfos = new ObservableCollection<ChengYuanInfo>(SimulationPTDAL.GetChengYuanInfos(ChengYuanCode, ChengYuanName, ageFrom, ageTo, ChengYuanGender));
              });

            ClearCommand = new RelayCommand((obj) =>
              {
                  ChengYuanCode = ChengYuanName = AgeStart = AgeEnd = ChengYuanGender = string.Empty;
              });

            DetailsCommand = new RelayCommand((obj) =>
              {
                  if (SelectedChengYuanInfo == null)
                  {
                      ModernDialog.ShowMessage("请先选择要查看的人员", string.Empty, System.Windows.MessageBoxButton.OK);
                      return;
                  }

                  ResetEditChengYuanInfo(SelectedChengYuanInfo);
              });
            AddCommand = new RelayCommand((obj) =>
              {
                  ResetEditChengYuanInfo();
              });
            DeleteCommand = new RelayCommand((obj) =>
              {
                  if (SelectedChengYuanInfo == null)
                  {
                      ModernDialog.ShowMessage("请先选择要删除的人员", string.Empty, System.Windows.MessageBoxButton.OK);
                      return;
                  }

                  if (ModernDialog.ShowMessage("是否要删除所选人员？", "提示", System.Windows.MessageBoxButton.OKCancel) == System.Windows.MessageBoxResult.OK)
                  {
                      SimulationPTDAL.DeleteChengYuanInfo(SelectedChengYuanInfo);
                      ChengYuanInfos.Remove(SelectedChengYuanInfo);
                  }
              });
            SaveCommand = new RelayCommand((obj) =>
              {
                  if (string.IsNullOrEmpty(EditChengYuanInfo.Code))
                  {
                      ModernDialog.ShowMessage("人员编号不能为空", string.Empty, System.Windows.MessageBoxButton.OK);
                      return;
                  }

                  if (string.IsNullOrEmpty(EditChengYuanInfo.Name))
                  {
                      ModernDialog.ShowMessage("人员姓名不能为空", string.Empty, System.Windows.MessageBoxButton.OK);
                      return;
                  }

                  if (string.IsNullOrEmpty(EditChengYuanInfo.Gender))
                  {
                      ModernDialog.ShowMessage("人员性别不能为空", string.Empty, System.Windows.MessageBoxButton.OK);
                      return;
                  }

                  int age = 0;
                  if (!int.TryParse(EditChengYuanInfo.Age, out age) || age <= 0)
                  {
                      ModernDialog.ShowMessage("请输入正确的年龄", string.Empty, System.Windows.MessageBoxButton.OK);
                      return;
                  }

                  int answerDeviceID = 0, sensorDeviceID = 0;
                  if (!int.TryParse(EditChengYuanInfo.AnswerDeviceID, out answerDeviceID) || answerDeviceID <= 0)
                  {
                      ModernDialog.ShowMessage("请输入正确的答题器编号", string.Empty, System.Windows.MessageBoxButton.OK);
                      return;
                  }
                  if (!int.TryParse(EditChengYuanInfo.SensorDeviceID, out sensorDeviceID) || sensorDeviceID <= 0)
                  {
                      ModernDialog.ShowMessage("请输入正确的传感器编号", string.Empty, System.Windows.MessageBoxButton.OK);
                      return;
                  }

                  if (SelectedChengYuanInfo != null && EditChengYuanInfo.Id == SelectedChengYuanInfo.Id)
                  {
                      SelectedChengYuanInfo.Code = EditChengYuanInfo.Code;
                      SelectedChengYuanInfo.Name = EditChengYuanInfo.Name;
                      SelectedChengYuanInfo.Age = age;
                      SelectedChengYuanInfo.Gender = EditChengYuanInfo.Gender;
                      SelectedChengYuanInfo.AnswerDeviceID = answerDeviceID;
                      SelectedChengYuanInfo.SensorDeviceID = sensorDeviceID;

                      SimulationPTDAL.UpdateChengYuanInfo(SelectedChengYuanInfo);
                  }
                  else
                  {
                      SimulationPTDAL.AddChengYuanInfo(new ChengYuanInfo
                      {
                          Code = EditChengYuanInfo.Code,
                          Name = EditChengYuanInfo.Name,
                          Age = age,
                          Gender = EditChengYuanInfo.Gender,
                          AnswerDeviceID = answerDeviceID,
                          SensorDeviceID = sensorDeviceID,
                      });
                  }

                  EditChengYuanInfo = null;
              });
            CancelCommand = new RelayCommand((obj) =>
              {
                  EditChengYuanInfo = null;
              });

            ImportCommand = new RelayCommand((obj) =>
              {
                  OpenFileDialog dialog = new OpenFileDialog();
                  dialog.Filter = "Excel 97-2003文件|*.xls";
                  if (dialog.ShowDialog() == DialogResult.OK)
                  {
                      string fileName = dialog.FileName;
                      if (!string.IsNullOrEmpty(fileName))
                      {
                          FileStream stream = null;
                          try
                          {
                              stream = new FileStream(fileName, FileMode.Open);
                          }
                          catch
                          {
                              ModernDialog.ShowMessage("请先关闭Excel文件再进行导入", "提示", System.Windows.MessageBoxButton.OK);
                              return;
                          }
                          try
                          {
                              DataTable table = RenderFromExcel(stream);
                              List<ChengYuanInfo> chengYuanInfos = SimulationPTContext.Instance.ChengYuanInfo.ToList();
                              List<ChengYuanInfo> newChengYuanInfos = new List<ChengYuanInfo>();
                              List<TeamInfo> newTeamInfos = new List<TeamInfo>();
                              int newChengYuanCount = 0;

                              for (int i = 0; i < table.Rows.Count; i++)
                              {
                                  if (table.Rows[i].Table.Columns.Count < 6)  // 如果当前行的内容格少于4个，跳过该行数据
                                      continue;

                                  ChengYuanInfo chengYuanInfo = new ChengYuanInfo
                                  {
                                      Code = table.Rows[i][0].ToString(),
                                  };
                                  if (chengYuanInfos.Any(c => c.Code == chengYuanInfo.Code))
                                      continue;

                                  chengYuanInfo.Name = table.Rows[i][1].ToString();
                                  chengYuanInfo.Gender = table.Rows[i][2].ToString();
                                  if (int.TryParse(table.Rows[i][3].ToString(), out int age))
                                      chengYuanInfo.Age = age;

                                  if (!int.TryParse(table.Rows[i][4].ToString(), out int answerDeviceId) || answerDeviceId <= 0)
                                      continue;
                                  chengYuanInfo.AnswerDeviceID = answerDeviceId;

                                  if (!int.TryParse(table.Rows[i][5].ToString(), out int sensorDeviceId) || sensorDeviceId <= 0)
                                      continue;
                                  chengYuanInfo.SensorDeviceID = sensorDeviceId;

                                  newChengYuanCount++;

                                  if (table.Rows[i].Table.Columns.Count >= 8)  // 单元格大于7个时处理团队信息
                                  {
                                      string teamCode = table.Rows[i][4].ToString();

                                      TeamInfo teamInfo = SimulationPTContext.Instance.TeamInfo.FirstOrDefault(t => t.Code == teamCode);
                                      if (teamInfo == null)
                                      {
                                          teamInfo = newTeamInfos.FirstOrDefault(t => t.Code == teamCode);
                                          if (teamInfo == null)
                                          {
                                              teamInfo = new TeamInfo { Code = teamCode, Name = table.Rows[i][5].ToString(), ChengYuanInfos = new List<ChengYuanInfo>() };
                                              newTeamInfos.Add(teamInfo);
                                          }
                                      }
                                      teamInfo.ChengYuanInfos.Add(chengYuanInfo);
                                      teamInfo.ChengYuanCount++;
                                  }
                                  else
                                      newChengYuanInfos.Add(chengYuanInfo);
                              }


                              if (newChengYuanInfos.Count > 0)
                                  SimulationPTContext.Instance.ChengYuanInfo.AddRange(newChengYuanInfos);
                              if (newTeamInfos.Count > 0)
                                  SimulationPTContext.Instance.TeamInfo.AddRange(newTeamInfos);

                              SimulationPTContext.Instance.SaveChanges();

                              ModernDialog.ShowMessage($"成功导入{newChengYuanCount}条人员信息", "提示", System.Windows.MessageBoxButton.OK);
                          }
                          catch (Exception ex)
                          {
                              ModernDialog.ShowMessage("导入数据失败!", "错误", System.Windows.MessageBoxButton.OK);
                              return;
                          }
                      }
                  }
              });
        }


        static DataTable RenderFromExcel(Stream excelFileStream)
        {
            using (excelFileStream)
            {
                IWorkbook workbook = new HSSFWorkbook(excelFileStream);

                ISheet sheet = workbook.GetSheetAt(0);//取第一个表
                DataTable table = new DataTable();

                IRow headerRow = sheet.GetRow(0);//第一行为标题行
                int cellCount = headerRow.LastCellNum;//LastCellNum = PhysicalNumberOfCells
                int rowCount = sheet.LastRowNum;//LastRowNum = PhysicalNumberOfRows - 1

                //handling header.
                for (int i = headerRow.FirstCellNum; i < cellCount; i++)
                {
                    DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue);
                    table.Columns.Add(column);
                }

                for (int i = (sheet.FirstRowNum + 1); i <= rowCount; i++)
                {
                    IRow row = sheet.GetRow(i);
                    DataRow dataRow = table.NewRow();

                    if (row != null)
                    {
                        for (int j = row.FirstCellNum; j < cellCount; j++)
                        {
                            ICell cell = row.GetCell(j);
                            if (cell != null)
                                dataRow[j] = GetCellValue(cell);
                        }
                    }

                    table.Rows.Add(dataRow);
                }
                return table;

            }
        }

        private static string GetCellValue(ICell cell)
        {
            if (cell == null)
                return string.Empty;
            switch (cell.CellType)
            {
                case CellType.Blank:
                    return string.Empty;
                case CellType.Boolean:
                    return cell.BooleanCellValue.ToString();
                case CellType.Error:
                    return cell.ErrorCellValue.ToString();
                case CellType.Numeric:
                case CellType.Unknown:
                default:
                    return cell.ToString();//This is a trick to get the correct value of the cell. NumericCellValue will return a numeric value no matter the cell value is a date or a number
                case CellType.String:
                    return cell.StringCellValue;
                case CellType.Formula:
                    try
                    {
                        HSSFFormulaEvaluator e = new HSSFFormulaEvaluator(cell.Sheet.Workbook);
                        e.EvaluateInCell(cell);
                        return cell.ToString();
                    }
                    catch
                    {
                        return cell.NumericCellValue.ToString();
                    }
            }
        }

        /// <summary>
        /// 重置编辑人员信息
        /// </summary>
        /// <param name="chengYuanInfo"></param>
        protected void ResetEditChengYuanInfo(ChengYuanInfo chengYuanInfo = null)
        {
            if (chengYuanInfo == null)
                EditChengYuanInfo = new EditChengYuanInfo();
            else
                EditChengYuanInfo = new EditChengYuanInfo
                {
                    Id = chengYuanInfo.Id,
                    Code = chengYuanInfo.Code,
                    Name = chengYuanInfo.Name,
                    Age = chengYuanInfo.Age.ToString(),
                    Gender = chengYuanInfo.Gender,
                    AnswerDeviceID = chengYuanInfo.AnswerDeviceID.ToString(),
                    SensorDeviceID = chengYuanInfo.SensorDeviceID.ToString(),
                };
        }

        public override void OnNavigatedFrom(NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);

            EditChengYuanInfo = null;
        }
    }

    /// <summary>
    /// 待编辑人员信息
    /// </summary>
    public class EditChengYuanInfo : LinnerToolkit.Core.Mvvm.NotifyPropertyChanged
    {
        private string code;
        private string name;
        private string gender;
        private string age;
        private string answerDeviceID;
        private string sensorDeviceID;

        /// <summary>
        /// Id
        /// </summary>
        public long Id { get; set; }
        /// <summary>
        /// 编号
        /// </summary>
        public string Code { get => code; set => SetProperty(ref code, value); }
        /// <summary>
        /// 姓名
        /// </summary>
        public string Name { get => name; set => SetProperty(ref name, value); }
        /// <summary>
        /// 性别
        /// </summary>
        public string Gender { get => gender; set => SetProperty(ref gender, value); }
        /// <summary>
        /// 年龄
        /// </summary>
        public string Age { get => age; set => SetProperty(ref age, value); }
        /// <summary>
        /// 答题器设备ID
        /// </summary>
        public string AnswerDeviceID { get => answerDeviceID; set => SetProperty(ref answerDeviceID, value); }
        /// <summary>
        /// 传感器设备ID
        /// </summary>
        public string SensorDeviceID { get => sensorDeviceID; set => SetProperty(ref sensorDeviceID, value); }
    }
}
